package cn.xiaopengstack.infrastructure.persistent.repository;

import cn.bugstack.middleware.db.router.strategy.IDBRouterStrategy;
import cn.xiaopengstack.domain.activity.event.ActivitySkuStockZeroMessageEvent;
import cn.xiaopengstack.domain.activity.model.aggregate.CreatePartakeOrderAggregate;
import cn.xiaopengstack.domain.activity.model.aggregate.CreateRechangeQuotaOrderAggregate;
import cn.xiaopengstack.domain.activity.model.entity.*;
import cn.xiaopengstack.domain.activity.model.valobj.ActivitySkuStockKeyVO;
import cn.xiaopengstack.domain.activity.model.valobj.ActivityStateVO;
import cn.xiaopengstack.domain.activity.repository.IRaffleActivityRepository;
import cn.xiaopengstack.domain.strategy.model.entity.UserEntity;
import cn.xiaopengstack.infrastructure.event.EventPublisher;
import cn.xiaopengstack.infrastructure.persistent.dao.*;
import cn.xiaopengstack.infrastructure.persistent.po.*;
import cn.xiaopengstack.infrastructure.persistent.redis.IRedisService;
import cn.xiaopengstack.types.common.Constants;
import cn.xiaopengstack.types.enums.ResponseCode;
import cn.xiaopengstack.types.exception.AppException;
import cn.xiaopengstack.types.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RQueue;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author jiangyangang
 */
@Component
@Slf4j
public class RaffleActivityRepository implements IRaffleActivityRepository {
    @Resource
    private IRaffleActivityDao raffleActivityDao;

    @Resource
    private IRaffleActivityCountDao raffleActivityCountDao;

    @Resource
    private IRaffleActivitySkuDao raffleActivitySkuDao;

    @Resource
    private IRaffleActivityAccountDao raffleActivityAccountDao;

    @Resource
    private IRaffleActivityOrderDao raffleActivityOrderDao;

    @Resource
    private IRaffleActivityAccountDayDao raffleActivityAccountDayDao;

    @Resource
    private IRaffleActivityAccountMonthDao raffleActivityAccountMonthDao;

    @Resource
    private IUserRaffleOrderDao userRaffleOrderDao;

    @Resource
    private IRedisService redisService;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private IDBRouterStrategy dbRouter;

    @Resource
    private EventPublisher eventPublisher;


    @Override
    public RaffleActivityEntity queryRaffleActivityByActivityId(Long activityId) {
        // 优先从缓存查
        String cacheKey = String.format(Constants.RedisKey.ACTIVITY_ENTITY_KEY, activityId);
        RaffleActivityEntity activityEntityCache = redisService.getValue(cacheKey);
        if (Objects.nonNull(activityEntityCache)) {
            return activityEntityCache;
        }

        RaffleActivity activity = raffleActivityDao.queryRaffleActivityByActivityId(activityId);

        RaffleActivityEntity activityEntity = new RaffleActivityEntity();
        BeanUtils.copyProperties(activity, activityEntity);
        activityEntity.setState(ActivityStateVO.valueOf(activity.getState()));
        redisService.setValue(cacheKey, activityEntity);
        return activityEntity;
    }

    @Override
    public RaffleActivitySkuEntity queryActivitySku(Long activitySkuId) {
        RaffleActivitySku raffleActivitySku = raffleActivitySkuDao.queryActivitySku(activitySkuId);
        RaffleActivitySkuEntity raffleActivitySkuEntity = new RaffleActivitySkuEntity();
        BeanUtils.copyProperties(raffleActivitySku, raffleActivitySkuEntity);

        return raffleActivitySkuEntity;
    }

    @Override
    public RaffleActivityCountEntity queryRaffleActivityCountByActivityCountId(Long countId) {
        String cacheKey = String.format(Constants.RedisKey.ACTIVITY_COUNT_KEY, countId);
        RaffleActivityCountEntity countCache = redisService.getValue(cacheKey);
        if (Objects.nonNull(countCache)) {
            return countCache;
        }

        RaffleActivityCount activityCount = raffleActivityCountDao.queryRaffleActivityCountByActivityCountId(countId);
        RaffleActivityCountEntity raffleActivityCountEntity = new RaffleActivityCountEntity();
        BeanUtils.copyProperties(activityCount, raffleActivityCountEntity);

        redisService.setValue(cacheKey, raffleActivityCountEntity);

        return raffleActivityCountEntity;
    }

    @Override
    public RaffleActivityAccountEntity queryActivityAccount(Long activityId, String userId) {
        String cacheKey = String.format(Constants.RedisKey.ACTIVITY_ACCOUNT_KEY, activityId, userId);
        RaffleActivityAccountEntity activityAccountCache = redisService.getValue(cacheKey);
        if (Objects.nonNull(activityAccountCache)) {
            return activityAccountCache;
        }
        RaffleActivityAccount activityAccountQuery = new RaffleActivityAccount();
        activityAccountQuery.setUserId(userId);
        activityAccountQuery.setActivityId(activityId);
        RaffleActivityAccount activityAccount = raffleActivityAccountDao.queryActivityAccount(activityAccountQuery);
        RaffleActivityAccountEntity accountEntity = new RaffleActivityAccountEntity();
        BeanUtils.copyProperties(activityAccount, accountEntity);

        redisService.setValue(cacheKey, accountEntity);
        return accountEntity;
    }

    @Override
    public void saveNoPayOrder(CreateRechangeQuotaOrderAggregate createOrderAggregate) {
        try {
            // 订单对象
            RaffleActivityOrderEntity activityOrderEntity = createOrderAggregate.getRaffleActivityOrderEntity();
            RaffleActivityOrder raffleActivityOrder = new RaffleActivityOrder();
            raffleActivityOrder.setUserId(activityOrderEntity.getUserId());
            raffleActivityOrder.setSku(activityOrderEntity.getSku());
            raffleActivityOrder.setActivityId(activityOrderEntity.getActivityId());
            raffleActivityOrder.setActivityName(activityOrderEntity.getActivityName());
            raffleActivityOrder.setStrategyId(activityOrderEntity.getStrategyId());
            raffleActivityOrder.setOrderId(activityOrderEntity.getOrderId());
            raffleActivityOrder.setOrderTime(activityOrderEntity.getOrderTime());
            raffleActivityOrder.setTotalCount(createOrderAggregate.getTotalCount());
            raffleActivityOrder.setDayCount(createOrderAggregate.getDayCount());
            raffleActivityOrder.setMonthCount(createOrderAggregate.getMonthCount());
            raffleActivityOrder.setState(activityOrderEntity.getState().getCode());
            raffleActivityOrder.setOutBusinessNo(activityOrderEntity.getOutBusinessNo());
            raffleActivityOrder.setPayAmount(activityOrderEntity.getPayAmount());

            // 账户对象
            RaffleActivityAccount raffleActivityAccount = new RaffleActivityAccount();
            raffleActivityAccount.setUserId(createOrderAggregate.getUserId());
            raffleActivityAccount.setActivityId(createOrderAggregate.getActivityEntity().getActivityId());
            raffleActivityAccount.setTotalCount(createOrderAggregate.getTotalCount());
            raffleActivityAccount.setTotalCountSurplus(createOrderAggregate.getTotalCount());
            raffleActivityAccount.setDayCount(createOrderAggregate.getDayCount());
            raffleActivityAccount.setDayCountSurplus(createOrderAggregate.getDayCount());
            raffleActivityAccount.setMonthCount(createOrderAggregate.getMonthCount());
            raffleActivityAccount.setMonthCountSurplus(createOrderAggregate.getMonthCount());
            
            // 日账户对象
            RaffleActivityAccountDay raffleActivityAccountDay = new RaffleActivityAccountDay();
            raffleActivityAccountDay.setUserId(createOrderAggregate.getUserId());
            raffleActivityAccountDay.setDayCount(createOrderAggregate.getDayCount());
            raffleActivityAccountDay.setActivityId(createOrderAggregate.getActivityEntity().getActivityId());
            raffleActivityAccountDay.setDayCountSurplus(createOrderAggregate.getDayCount());
            raffleActivityAccountDay.setCreateTime(new Date());
            raffleActivityAccountDay.setDay(TimeUtils.dateToString(new Date(createOrderAggregate.getRechargeTime()), TimeUtils.YYYY_MM_DD));

            // 月账户对象
            RaffleActivityAccountMonth raffleActivityAccountMonth = new RaffleActivityAccountMonth();
            raffleActivityAccountMonth.setUserId(createOrderAggregate.getUserId());
            raffleActivityAccountMonth.setMonthCount(createOrderAggregate.getMonthCount());
            raffleActivityAccountMonth.setActivityId(createOrderAggregate.getActivityEntity().getActivityId());
            raffleActivityAccountMonth.setMonthCountSurplus(createOrderAggregate.getMonthCount());
            raffleActivityAccountMonth.setCreateTime(new Date());
            raffleActivityAccountMonth.setMonth(TimeUtils.dateToString(new Date(createOrderAggregate.getRechargeTime()), TimeUtils.YYYY_MM));

            // 设置分片键
            dbRouter.doRouter(createOrderAggregate.getUserId());

            // 手动事务控制
            transactionTemplate.execute(state -> {
                try {
                    // 插入订单
                    raffleActivityOrderDao.insertSelective(raffleActivityOrder);

                    // 更新账户
                    int count = raffleActivityAccountDao.updateAccountQuota(raffleActivityAccount);
                    // 账户不存在则插入
                    if (count == 0) {
                        raffleActivityAccountDao.insertSelective(raffleActivityAccount);
                    }

                    // 更新日账户
                    raffleActivityAccountDayDao.updateAccountQuota(raffleActivityAccountDay);

                    // 更新月账户
                    raffleActivityAccountMonthDao.updateAccountQuota(raffleActivityAccountMonth);

                    return "1";
                } catch (Exception e) {
                    state.setRollbackOnly();
                    throw new AppException(ResponseCode.UN_ERROR.getCode(), e);
                }
            });
        } catch (Exception e) {
            log.error("更新账户信息失败", e);
            throw e;
        } finally {
            // 清除分片键
            dbRouter.clear();
        }
    }

    @Override
    public void saveCreditExchangeOrder(CreateRechangeQuotaOrderAggregate createOrderAggregate) {
        try {
            // 订单对象
            RaffleActivityOrderEntity activityOrderEntity = createOrderAggregate.getRaffleActivityOrderEntity();
            RaffleActivityOrder raffleActivityOrder = new RaffleActivityOrder();
            raffleActivityOrder.setUserId(activityOrderEntity.getUserId());
            raffleActivityOrder.setSku(activityOrderEntity.getSku());
            raffleActivityOrder.setActivityId(activityOrderEntity.getActivityId());
            raffleActivityOrder.setActivityName(activityOrderEntity.getActivityName());
            raffleActivityOrder.setStrategyId(activityOrderEntity.getStrategyId());
            raffleActivityOrder.setOrderId(activityOrderEntity.getOrderId());
            raffleActivityOrder.setOrderTime(activityOrderEntity.getOrderTime());
            raffleActivityOrder.setTotalCount(createOrderAggregate.getTotalCount());
            raffleActivityOrder.setDayCount(createOrderAggregate.getDayCount());
            raffleActivityOrder.setMonthCount(createOrderAggregate.getMonthCount());
            raffleActivityOrder.setState(activityOrderEntity.getState().getCode());
            raffleActivityOrder.setOutBusinessNo(activityOrderEntity.getOutBusinessNo());
            raffleActivityOrder.setPayAmount(createOrderAggregate.getRaffleActivityOrderEntity().getPayAmount());

            // 设置分片键
            dbRouter.doRouter(createOrderAggregate.getUserId());
            // 插入订单
            raffleActivityOrderDao.insertSelective(raffleActivityOrder);
        }  finally {
            // 清除分片键
            dbRouter.clear();
        }
    }

    @Override
    public void cacheActivitySkuStockCount(Long skuId, Integer stockCount) {
        String cacheKey = String.format(Constants.RedisKey.ACTIVITY_SKU_STOCK_KEY, skuId);
        if (redisService.isExists(cacheKey)) {
            return;
        }
        // 设置缓存
        redisService.setAtomicLong(cacheKey, stockCount.longValue());
    }

    @Override
    public boolean subtractionActivitySkuStock(ActivitySkuStockKeyVO stockKeyVO) {
        // 扣减sku库存
        String skuStockKey = String.format(Constants.RedisKey.ACTIVITY_SKU_STOCK_KEY, stockKeyVO.getSku());

        long leftSkuStock = redisService.decrBy(skuStockKey, stockKeyVO.getDecrNumber());

        // 库存耗尽
        if (0 == leftSkuStock) {
            // 触发MQ更新DB库存数量
            ActivitySkuStockZeroMessageEvent<ActivitySkuStockZeroMessageEvent.ActivitySkuStockZeroMessage> event =
                    new ActivitySkuStockZeroMessageEvent<>(ActivitySkuStockZeroMessageEvent.ActivitySkuStockZeroMessage.builder()
                    .activityId(stockKeyVO.getActivityId())
                    .sku(stockKeyVO.getSku())
                    .endTime(stockKeyVO.getEndTime())
                    .decrNumber(stockKeyVO.getDecrNumber()).build(), stockKeyVO.getSku().toString());

            eventPublisher.publish(event);

            return false;
        } else if (0 > leftSkuStock) {
            // 库存不足
            redisService.setAtomicLong(skuStockKey, 0L);
            return false;
        }

        // 库存扣减锁
        String decrSkuStockLockKey = String.format(Constants.RedisKey.ACTIVITY_SKU_STOCK_LOCK_KEY, stockKeyVO.getSku(), leftSkuStock);
        // 过期时间延期1天
        long expiredTime = stockKeyVO.getEndTime() - System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1);

        Boolean lock = redisService.setNx(decrSkuStockLockKey, expiredTime, TimeUnit.MILLISECONDS);
        if (!lock) {
            log.info("活动sku库存加锁失败 {}", decrSkuStockLockKey);
        }

        return lock;
    }

    @Override
    public void produceActivitySkuStockDecrQueue(ActivitySkuStockKeyVO stockKeyVO) {
        String cacheKey = String.format(Constants.RedisKey.ACTIVITY_SKU_STOCK_QUEUE_KEY, stockKeyVO.getActivityId(), stockKeyVO.getSku());
        RBlockingQueue<ActivitySkuStockKeyVO> blockingQueue = redisService.getBlockingQueue(cacheKey);
        RDelayedQueue<ActivitySkuStockKeyVO> delayedQueue = redisService.getDelayedQueue(blockingQueue);
        // 延迟3秒后放入队列
        delayedQueue.offer(stockKeyVO, 3, TimeUnit.SECONDS);
    }

    @Override
    public ActivitySkuStockKeyVO consumeActivitySkuStockDecrQueue() throws InterruptedException{
        String cacheKey = Constants.RedisKey.ACTIVITY_SKU_STOCK_QUEUE_KEY;
        boolean exists = redisService.isExists(cacheKey);
        if (!exists) {
            return null;
        }

        RQueue<ActivitySkuStockKeyVO> queue = redisService.getQueue(cacheKey);

        return queue.poll();
    }

    @Override
    public void clearActivitySkuStockDecrQueue(ActivitySkuStockKeyVO stockKeyVO) {
        String cacheKey = String.format(Constants.RedisKey.ACTIVITY_SKU_STOCK_QUEUE_KEY, stockKeyVO.getActivityId(), stockKeyVO.getSku());
        RBlockingQueue<ActivitySkuStockKeyVO> blockingQueue = redisService.getBlockingQueue(cacheKey);
        blockingQueue.clear();
    }

    @Override
    public void updateActivitySkuStock(Long skuId, Integer decrNumber) {
        raffleActivitySkuDao.updateActivitySkuStock(skuId, decrNumber);
    }

    @Override
    public void clearActivitySkuStock(Long skuId) {
        raffleActivitySkuDao.clearActivitySkuStock(skuId);
    }

    @Override
    public Integer queryActivitySkuStockCache(Long sku) {
        String cacheKey = String.format(Constants.RedisKey.ACTIVITY_SKU_STOCK_KEY, sku);
        if (!redisService.isExists(cacheKey)) {
            return 0;
        }
        return redisService.getValue(cacheKey);
    }

    @Override
    public void saveUserRafflePartakeOrder(CreatePartakeOrderAggregate orderAggregate) {
        UserRaffleOrderEntity userRaffleOrderEntity = orderAggregate.getUserRaffleOrderEntity();
        ActivityAccountDayEntity activityAccountDayEntity = orderAggregate.getActivityAccountDayEntity();
        ActivityAccountMonthEntity activityAccountMonthEntity = orderAggregate.getActivityAccountMonthEntity();
        UserEntity userEntity = orderAggregate.getUser();
        Long activityId = orderAggregate.getActivityId();
        Integer decrNumber = orderAggregate.getDecrNumber();
        try {

            dbRouter.doRouter(userEntity.getUserId());

            transactionTemplate.execute(state -> {
                try {

                    // 更新总账单
                    int numAccount = raffleActivityAccountDao.updateActivityAccountSubtractionQuota(userEntity.getUserId(),
                            activityId,
                            decrNumber);

                    if (1 != numAccount) {
                        // 更新失败
                        throw new AppException(ResponseCode.ACTIVITY_PARTAKE_ORDER_FAIL.getCode(), ResponseCode.ACTIVITY_PARTAKE_ORDER_FAIL.getInfo());
                    }

                    // 保存日账户
                    if (orderAggregate.isExistAccountDay()) {
                        // 更新日账户
                        RaffleActivityAccountDay raffleActivityAccountDay = new RaffleActivityAccountDay();
                        raffleActivityAccountDay.setUserId(userEntity.getUserId());
                        raffleActivityAccountDay.setActivityId(activityId);
                        raffleActivityAccountDay.setDay(activityAccountDayEntity.getDay());
                        int numDay = raffleActivityAccountDayDao.updateActivityAccountDaySubtractionQuota(raffleActivityAccountDay);
                        if (1 != numDay) {
                            // 更新失败
                            throw new AppException(ResponseCode.ACTIVITY_PARTAKE_ORDER_FAIL.getCode(), ResponseCode.ACTIVITY_PARTAKE_ORDER_FAIL.getInfo());
                        }

                    } else {
                        RaffleActivityAccountDay raffleActivityAccountDay = new RaffleActivityAccountDay();
                        raffleActivityAccountDay.setActivityId(activityAccountDayEntity.getActivityId());
                        raffleActivityAccountDay.setUserId(userEntity.getUserId());
                        raffleActivityAccountDay.setDayCount(activityAccountDayEntity.getDayCount());
                        raffleActivityAccountDay.setDayCountSurplus(activityAccountDayEntity.getDayCountSurplus() - decrNumber);
                        raffleActivityAccountDay.setDay(activityAccountDayEntity.getDay());
                        raffleActivityAccountDay.setCreateTime(new Date());
                        raffleActivityAccountDay.setUpdateTime(new Date());
                        raffleActivityAccountDayDao.insert(raffleActivityAccountDay);


                        // 更新镜像
                        raffleActivityAccountDao.updateActivityAccountMonthSurplusImageQuota(
                                userEntity.getUserId(),
                                activityAccountDayEntity.getActivityId(),
                                activityAccountDayEntity.getDayCountSurplus(),
                                decrNumber);
                    }

                    // 保存月账户
                    if (orderAggregate.isExistAccountMonth()) {
                        RaffleActivityAccountMonth accountMonth = new RaffleActivityAccountMonth();
                        accountMonth.setUserId(userEntity.getUserId());
                        accountMonth.setActivityId(activityId);
                        accountMonth.setMonth(activityAccountMonthEntity.getMonth());
                        int numMonth = raffleActivityAccountMonthDao.updateActivityAccountMonthSubtractionQuota(accountMonth);
                        if (1 != numMonth) {
                            // 更新失败
                            throw new AppException(ResponseCode.ACTIVITY_PARTAKE_ORDER_FAIL.getCode(), ResponseCode.ACTIVITY_PARTAKE_ORDER_FAIL.getInfo());
                        }
                    } else {
                        RaffleActivityAccountMonth raffleActivityAccountMonth = new RaffleActivityAccountMonth();
                        raffleActivityAccountMonth.setActivityId(activityAccountMonthEntity.getActivityId());
                        raffleActivityAccountMonth.setUserId(userEntity.getUserId());
                        raffleActivityAccountMonth.setMonthCount(activityAccountMonthEntity.getMonthCount());
                        raffleActivityAccountMonth.setMonthCountSurplus(activityAccountMonthEntity.getMonthCountSurplus() - decrNumber);
                        raffleActivityAccountMonth.setMonth(activityAccountMonthEntity.getMonth());
                        raffleActivityAccountMonth.setCreateTime(new Date());
                        raffleActivityAccountMonth.setUpdateTime(new Date());
                        raffleActivityAccountMonthDao.insertSelective(raffleActivityAccountMonth);

                        // 更新镜像
                        raffleActivityAccountDao.updateActivityAccountMonthSurplusImageQuota(
                                userEntity.getUserId(),
                                activityAccountMonthEntity.getActivityId(),
                                activityAccountMonthEntity.getMonthCountSurplus(),
                                decrNumber);
                    }


                    // 保存用户抽奖单
                    UserRaffleOrder userRaffleOrder = new UserRaffleOrder();
                    userRaffleOrder.setActivityId(userRaffleOrderEntity.getActivityEntity().getActivityId());
                    userRaffleOrder.setActivityName(userRaffleOrderEntity.getActivityName());
                    userRaffleOrder.setUserId(userRaffleOrderEntity.getUserId());
                    userRaffleOrder.setStrategyId(userRaffleOrderEntity.getStrategyId());
                    userRaffleOrder.setOrderId(userRaffleOrderEntity.getOrderId());
                    userRaffleOrder.setOrderState(userRaffleOrderEntity.getOrderState().getCode());
                    userRaffleOrder.setOrderTime(userRaffleOrderEntity.getOrderTime());
                    userRaffleOrder.setCreateTime(new Date());
                    userRaffleOrder.setUpdateTime(new Date());
                    userRaffleOrderDao.insertSelective(userRaffleOrder);

                    return 1;
                } catch (DuplicateKeyException e) {
                    state.setRollbackOnly();
                    log.error("写入创建参与活动记录，唯一索引冲突 userId: {} activityId: {}", userEntity.getUserId(), activityId, e);
                    throw new AppException(ResponseCode.INDEX_DUP.getCode(), e);
                } catch (Exception e) {
                    state.setRollbackOnly();
                    throw e;
                }
            });


        } finally {
            dbRouter.clear();
        }
    }

    @Override
    public RaffleActivityAccountEntity queryActivityAccountByUserId(String userId, Long activityId) {
        RaffleActivityAccount activityAccountQuery = new RaffleActivityAccount();
        activityAccountQuery.setUserId(userId);
        activityAccountQuery.setActivityId(activityId);

        RaffleActivityAccount activityAccount = raffleActivityAccountDao.queryActivityAccount(activityAccountQuery);
        RaffleActivityAccountEntity accountEntity = new RaffleActivityAccountEntity();
        BeanUtils.copyProperties(activityAccount, accountEntity);
        return accountEntity;
    }

    @Override
    public ActivityAccountMonthEntity queryActivityAccountMonthByUserId(String userId, Long activityId, String month) {
        RaffleActivityAccountMonth accountMonthQuery = new RaffleActivityAccountMonth();
        accountMonthQuery.setUserId(userId);
        accountMonthQuery.setMonth(month);
        accountMonthQuery.setActivityId(activityId);
        RaffleActivityAccountMonth raffleActivityAccountMonth = raffleActivityAccountMonthDao.queryActivityAccountMonthByUserId(accountMonthQuery);
        if (Objects.isNull(raffleActivityAccountMonth)) {
            return null;
        }
        ActivityAccountMonthEntity activityAccountMonthEntity = new ActivityAccountMonthEntity();
        BeanUtils.copyProperties(raffleActivityAccountMonth, activityAccountMonthEntity);
        return activityAccountMonthEntity;
    }

    @Override
    public ActivityAccountDayEntity queryActivityAccountDayByUserId(String userId, Long activityId, String day) {
        RaffleActivityAccountDay accountDay = new RaffleActivityAccountDay();
        accountDay.setDay(day);
        accountDay.setUserId(userId);
        accountDay.setActivityId(activityId);
        RaffleActivityAccountDay raffleActivityAccountDay = raffleActivityAccountDayDao.queryActivityAccountDayByUserId(accountDay);
        if (Objects.isNull(raffleActivityAccountDay)) {
            return null;
        }

        ActivityAccountDayEntity activityAccountDayEntity = new ActivityAccountDayEntity();
        BeanUtils.copyProperties(raffleActivityAccountDay, activityAccountDayEntity);
        return activityAccountDayEntity;
    }

    @Override
    public UserRaffleOrderEntity queryRaffleActivityUnusedPartakeOrderByUid(Long activityId, String userId) {
        UserRaffleOrder userRaffleOrder = new UserRaffleOrder();
        userRaffleOrder.setUserId(userId);
        userRaffleOrder.setActivityId(activityId);
        UserRaffleOrder raffleOrder = userRaffleOrderDao.queryRaffleActivityUnusedPartakeOrderByUid(userRaffleOrder);
        if (Objects.isNull(raffleOrder)) {
            return null;
        }

        UserRaffleOrderEntity userRaffleOrderEntity = new UserRaffleOrderEntity();
        BeanUtils.copyProperties(raffleOrder, userRaffleOrderEntity);
        return userRaffleOrderEntity;
    }

    @Override
    public List<RaffleActivitySkuEntity> queryActivitySkuByActivityId(Long activityId) {
        List<RaffleActivitySku> raffleActivitySkus = raffleActivitySkuDao.queryByActivityId(activityId);

        return raffleActivitySkus.stream().map(sku -> {
            RaffleActivitySkuEntity raffleActivitySkuEntity = new RaffleActivitySkuEntity();
            BeanUtils.copyProperties(sku, raffleActivitySkuEntity);
            return raffleActivitySkuEntity;
        }).collect(Collectors.toList());

    }

    @Override
    public void updateTradeOrder(RechangeTradeResultEntity rechangeTradeResult) {
        try{
            // 设置分片键
            dbRouter.doRouter(rechangeTradeResult.getUserId());
            String orderId = rechangeTradeResult.getOrderId();
            String userId = rechangeTradeResult.getUserId();
            RaffleActivityOrder order = raffleActivityOrderDao.queryOrderByUserIdAndOrderId(userId, orderId);
            if (Objects.isNull(order)) {
                throw new AppException(ResponseCode.ACTIVITY_RECHANGE_UPDATE_TRADE_ORDER_ERROR.getCode(), ResponseCode.ACTIVITY_RECHANGE_UPDATE_TRADE_ORDER_ERROR.getInfo());
            }

            // 账户对象
            RaffleActivityAccount raffleActivityAccount = new RaffleActivityAccount();
            raffleActivityAccount.setUserId(order.getUserId());
            raffleActivityAccount.setActivityId(order.getActivityId());
            raffleActivityAccount.setTotalCount(order.getTotalCount());
            raffleActivityAccount.setTotalCountSurplus(order.getTotalCount());
            raffleActivityAccount.setDayCount(order.getDayCount());
            raffleActivityAccount.setDayCountSurplus(order.getDayCount());
            raffleActivityAccount.setMonthCount(order.getMonthCount());
            raffleActivityAccount.setMonthCountSurplus(order.getMonthCount());

            // 日账户对象
            RaffleActivityAccountDay raffleActivityAccountDay = new RaffleActivityAccountDay();
            raffleActivityAccountDay.setUserId(order.getUserId());
            raffleActivityAccountDay.setDayCount(order.getDayCount());
            raffleActivityAccountDay.setActivityId(order.getActivityId());
            raffleActivityAccountDay.setDayCountSurplus(order.getDayCount());
            raffleActivityAccountDay.setCreateTime(new Date());
            raffleActivityAccountDay.setDay(TimeUtils.dateToString(order.getCreateTime(), TimeUtils.YYYY_MM_DD));

            // 月账户对象
            RaffleActivityAccountMonth raffleActivityAccountMonth = new RaffleActivityAccountMonth();
            raffleActivityAccountMonth.setUserId(order.getUserId());
            raffleActivityAccountMonth.setMonthCount(order.getMonthCount());
            raffleActivityAccountMonth.setActivityId(order.getActivityId());
            raffleActivityAccountMonth.setMonthCountSurplus(order.getMonthCount());
            raffleActivityAccountMonth.setCreateTime(new Date());
            raffleActivityAccountMonth.setMonth(TimeUtils.dateToString(order.getCreateTime(), TimeUtils.YYYY_MM));


            // 手动事务控制
            transactionTemplate.execute(state -> {
                try {
                    // 更新订单
                    RaffleActivityOrder orderForUpdate = new RaffleActivityOrder();
                    BeanUtils.copyProperties(order, orderForUpdate);
                    orderForUpdate.setState(rechangeTradeResult.getOrderStateVO().getCode());
                    orderForUpdate.setUpdateTime(new Date());

                    // 订单更新失败
                    int updatedResult = raffleActivityOrderDao.updateOrderStatus(orderForUpdate);
                    if (updatedResult <= 0) {
                        log.error("活动返利更新交易类订单失败，userId:{}, orderId:{}", order.getUserId(), order.getOrderId());
                        throw new AppException(ResponseCode.ACTIVITY_RECHANGE_UPDATE_TRADE_ORDER_ERROR.getCode(), ResponseCode.ACTIVITY_RECHANGE_UPDATE_TRADE_ORDER_ERROR.getInfo());
                    }

                    // 更新账户
                    int count = raffleActivityAccountDao.updateAccountQuota(raffleActivityAccount);
                    // 账户不存在则插入
                    if (count == 0) {
                        raffleActivityAccountDao.insertSelective(raffleActivityAccount);
                    }

                    // 更新日账户
                    raffleActivityAccountDayDao.updateAccountQuota(raffleActivityAccountDay);

                    // 更新月账户
                    raffleActivityAccountMonthDao.updateAccountQuota(raffleActivityAccountMonth);

                    return "1";
                } catch (Exception e) {
                    state.setRollbackOnly();
                    throw new AppException(ResponseCode.UN_ERROR.getCode(), e);
                }
            });
        } finally {
            // 清除分片键
            dbRouter.clear();
        }

    }

    @Override
    public List<SkuProductEntity> querySkuProducts(Long activityId) {
        List<RaffleActivitySku> raffleActivitySkus = raffleActivitySkuDao.queryByActivityId(activityId);
        ArrayList<SkuProductEntity> skuProductEntityArrayList = new ArrayList<>();
        for (RaffleActivitySku sku : raffleActivitySkus) {
            RaffleActivityCount activityCount = raffleActivityCountDao.queryRaffleActivityCountByActivityCountId(sku.getActivityCountId());

            SkuProductEntity skuProductEntity = SkuProductEntity.builder()
                    .productAmount(sku.getProductAmount())
                    .activityCountId(sku.getActivityCountId())
                    .stockCountSurplus(sku.getStockCountSurplus())
                    .activityCount(SkuProductEntity.ActivityCount.builder()
                            .monthCount(activityCount.getMonthCount())
                            .dayCount(activityCount.getDayCount())
                            .totalCount(activityCount.getTotalCount()).build())
                    .stockCount(sku.getStockCount())
                    .activityId(activityId)
                    .sku(sku.getSku()).build();

            skuProductEntityArrayList.add(skuProductEntity);
        }

        return skuProductEntityArrayList;
    }
}
